package org.gpp.proj1.util;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.StringTokenizer;

import com.jme.image.Texture;
import com.jme.scene.state.TextureState;
import com.jme.system.DisplaySystem;
import com.jme.util.LoggingSystem;
import com.jme.util.TextureManager;

/**
 * Loads and caches texture states
 * 
 * @author Paolo Victor, paolovictor@gmail.com
 */
public class TextureStateFactory {

	private static final String TEXTURE_LIST_FILE = "res/textures/textures.lst";

	private static final String WRAP_CONFIG = "wrap";
	
	private static final String NO_WRAP_CONFIG = "nowrap";
	
	private static TextureStateFactory instance = null;
	
	private Map< Integer, TextureState > textureStates = null;
	
	private Map< String, TextureState > directNamedTextureStates;
	
	private TextureStateFactory() {		
		directNamedTextureStates = new HashMap< String, TextureState >();
		
		this.loadTextures();
	}
	
	private void loadTextures() {
		textureStates = new HashMap< Integer, TextureState >();
		
		InputStream in = null;
		try {
			in = new BufferedInputStream( new FileInputStream( TEXTURE_LIST_FILE ) );
			Scanner scanner = new Scanner( in );
			
			int id = 0;
			while( scanner.hasNext() ) {
				String line = scanner.nextLine();
								
				// Ignoring blank and comment lines
				if( line.trim().equals( "" ) || line.charAt(0) == '#' ) {
					continue;
				}
				
				StringTokenizer tk = new StringTokenizer( line );
				
				// Loading texture file
				String textureFile = tk.nextToken();
				String wrap = tk.hasMoreTokens() ? tk.nextToken() : NO_WRAP_CONFIG;
				
				TextureState textureState = createTextureState( textureFile, wrap );

			    
			    this.textureStates.put( id, textureState );
			    this.directNamedTextureStates.put( textureFile , textureState );
			    
			    id++;
			}
		} catch (FileNotFoundException e) {
			LoggingSystem.getLogger().warning( "Can't load texture list file" );
			LoggingSystem.getLogger().throwing( this.getClass().getName(), "loadTextures", e );
			
			return;
		} finally {
			if( in != null ) {
				try {
					in.close();
				} catch (IOException e) {
				}
			}
		}
	}
	
	private TextureState createTextureState( String textureFile, String wrap ) {
		Texture texture = TextureManager.loadTexture( textureFile, Texture.MM_LINEAR_LINEAR, Texture.FM_LINEAR);
		
		if( wrap.equals( WRAP_CONFIG ) ) {
			texture.setWrap( Texture.WM_WRAP_S_WRAP_T );
		}
		
		// Creating texture state
	    TextureState textureState = DisplaySystem.getDisplaySystem().getRenderer().createTextureState();
	    textureState.setTexture( texture );
	    textureState.setEnabled(true);
	    
	    return textureState;
	}

	public static TextureStateFactory getInstance() {
		
		if( instance == null ) {
			instance = new TextureStateFactory();
		}
		
		return instance;
	}
	
	public TextureState getTextureState( int textureId ) {
		if( textureStates == null ) {
			this.loadTextures();
		}
		
		if( textureStates.containsKey( textureId ) ) {
			return textureStates.get( textureId );
		}
		
		return null;
	}

	public TextureState getTextureState( String textureFile ) {
		if( !directNamedTextureStates.containsKey( textureFile ) ) {
			directNamedTextureStates.put( textureFile, this.createTextureState( textureFile, NO_WRAP_CONFIG ) );
		}
		
		return directNamedTextureStates.get( textureFile );
	}

}
